<?php

namespace app\common\command\task;

use app\api\logic\BuildAIQuestionFormat;
use app\common\exception\BusinessException;
use app\common\model\AiExplanationTask;
use app\common\model\AppConfig;
use app\common\model\CourseQuestion;
use app\common\model\CourseQuestionBackground;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * php think cron buildAiExplanation
 */
class BuildAiExplanation
{
    /**
     * invoke
     * @throws
     */
    public function invoke()
    {
        // 获取待处理数据
        $where = [['status', '=', 1]];
        $list1 = app(AiExplanationTask::class)->field('id,app_id,question_id,ask,retry')->where($where)->limit(3)->select();
        $list1 = $list1 ? $list1->toArray() : [];

        // 获取已失败数据
        $where = [['status', '=', 3], ['retry', '<=', 11]];
        $list2 = app(AiExplanationTask::class)->field('id,app_id,question_id,ask,retry')->where($where)->limit(3)->select();
        $list2 = $list2 ? $list2->toArray() : [];

        // 循环处理题目
        $list = array_merge($list1, $list2);
        foreach ($list as $item) {
            // 提取参数
            $questionId = $item['question_id'];
            echo '开始执行题目编号' . $questionId . PHP_EOL;
            $this->executeItem($item);
            echo '结束执行题目编号' . $questionId . PHP_EOL;
        }
    }

    /**
     * executeItem
     * @throws DataNotFoundException
     * @throws BusinessException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    private function executeItem($item)
    {
        // 提取参数
        $appId = $item['app_id'];
        $questionId = $item['question_id'];

        // 查询题目信息
        $question = app(CourseQuestion::class)->find($questionId);
        $questionData = json_decode($question->question_data, true);
        if (!$questionData) {
            throw new BusinessException('解析题目数据失败');
        }

        // 存在题目背景需要添加
        if ($question['background_id']) {
            $where = [['id', '=', $question['background_id']]];
            $questionBackground = app(CourseQuestionBackground::class)->where($where)->value('value', '');
        }

        // 调用ai生成解析
        $moonShotService = null;
        $answer = $error = '';
        try {

            // 生成询问词
            $ask = $item['ask'];
            if (!$ask) {
                $ask = (new BuildAIQuestionFormat($questionData, $questionBackground ?? []))->build();
            }

            // 读取配置
            $config = app(AppConfig::class)->getByIdAndType($appId, 'moonShot');

            // 初始化服务
            $aiClass = 'app\common\service\\' . $config['apiService'];
            $moonShotService = app($aiClass, [], true);
            $moonShotService->setApiHost(($config['apiHost']));
            $max = 3;
            while ($max--) {
                // 如果配置api睡眠时间则等待
                if ($config['apiSleepTime'] > 0) {
                    sleep($config['apiSleepTime']);
                }
                // 调用ai
                $answer = $moonShotService->setApiKey($config['apiKey'])->setRoleRule($config['aiExplanationRoleRule'])->chat($ask);
                $answer = trim($answer);
                if ($answer) {
                    break;
                }
            }
        } catch (\Exception $e) {
            $error = $moonShotService ? $moonShotService->getResponse() : $e->getMessage();
        }

        // 保存记录
        $time = time();
        $saveData = [
            'question_id' => $questionId,
            'ask' => $ask ?? '',
            'answer' => $answer,
            'status' => !empty($answer) ? 2 : 3,
            'error' => $error,
            'retry' => $item['retry'] + 1,
            'update_time' => $time,
        ];
        $isSave = app(AiExplanationTask::class)->save_data($saveData, ['id' => $item['id']]);
        if (!$isSave) {
            throw new BusinessException('保存结果失败');
        }
    }
}